/**
 * API服务层 - 处理与MCP服务的通信
 */
import { RequestLimiter } from '../utils/RequestLimiter';

// 创建一个RequestLimiter实例
const requestLimiter = new RequestLimiter(30, 1000);

// 基础请求URL
const API_BASE_URL = '/api/mcp/amap_maps_maps';

// 默认超时时间（毫秒）
const DEFAULT_TIMEOUT = 15000;

// 重试配置
const RETRY_CONFIG = {
  maxRetries: 3,        // 最大重试次数
  baseDelay: 1000,      // 基础重试延迟（毫秒）
  maxDelay: 5000        // 最大重试延迟（毫秒）
};

/**
 * 发送API请求，处理错误和超时
 * @param endpoint API端点
 * @param params 查询参数
 * @param options 额外选项
 * @returns 请求结果
 */
export const fetchAPI = async <T>(
  endpoint: string, 
  params: Record<string, string> = {}, 
  options: RequestInit = {}
): Promise<T> => {
  // 将API请求包装为函数，以便可以通过限流器调用
  const apiCall = async (): Promise<T> => {
    try {
      // 构建查询参数字符串
      const queryParams = new URLSearchParams();
      Object.entries(params).forEach(([key, value]) => {
        queryParams.append(key, value);
      });
      
      // 构建完整URL
      const url = `${API_BASE_URL}${endpoint}?${queryParams.toString()}`;
      console.log(`发起API请求: ${url}`);
      
      // 设置超时
      const controller = new AbortController();
      const timeoutId = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT);
      
      // 合并选项
      const mergedOptions: RequestInit = {
        ...options,
        signal: controller.signal,
        headers: {
          'Accept': 'application/json',
          ...(options.headers || {})
        }
      };
      
      // 发送请求
      const response = await fetch(url, mergedOptions);
      
      // 清除超时
      clearTimeout(timeoutId);
      
      // 检查响应状态
      if (!response.ok) {
        throw new Error(`请求失败，状态码: ${response.status}`);
      }
      
      // 检查内容类型
      const contentType = response.headers.get('content-type');
      if (!contentType || !contentType.includes('application/json')) {
        console.warn(`响应不是JSON格式: ${contentType}`);
        const text = await response.text();
        
        // 尝试从错误文本中解析JSON
        if (text.includes('{') && text.includes('}')) {
          try {
            const cleanedText = text.substring(text.indexOf('{'), text.lastIndexOf('}') + 1);
            const jsonData = JSON.parse(cleanedText) as any;
            
            // 检查高德API的错误响应
            if (jsonData.status === '0' && jsonData.info === 'CUQPS_HAS_EXCEEDED_THE_LIMIT') {
              throw new Error(`CUQPS_HAS_EXCEEDED_THE_LIMIT: ${jsonData.infocode}`);
            }
            
            return jsonData as T;
          } catch (e) {
            console.error('尝试解析JSON失败:', e);
            throw e;
          }
        }
        
        throw new Error(`响应不是JSON格式: ${contentType}`);
      }
      
      // 解析JSON响应
      const jsonData = await response.json() as any;
      
      // 检查高德API的错误响应
      if (jsonData.status === '0' && jsonData.info === 'CUQPS_HAS_EXCEEDED_THE_LIMIT') {
        console.warn('API并发限制错误:', jsonData);
        throw new Error(`CUQPS_HAS_EXCEEDED_THE_LIMIT: ${jsonData.infocode}`);
      }
      
      return jsonData as T;
    } catch (error: any) {
      // 捕获并重新抛出错误，以便限流器处理
      console.error(`API请求失败 (${endpoint}):`, error);
      
      // 如果是并发限制错误，添加特殊标记以便限流器识别
      if (error && error.message && error.message.includes('CUQPS_HAS_EXCEEDED_THE_LIMIT')) {
        const e = new Error(error.message);
        (e as any).info = 'CUQPS_HAS_EXCEEDED_THE_LIMIT';
        throw e;
      }
      
      throw error;
    }
  };
  
  // 通过限流器提交请求
  return requestLimiter.submitService(apiCall);
};

/**
 * 地理编码 - 地址转坐标
 */
export const geocode = async (address: string) => {
  return fetchAPI('_geo', { address });
};

/**
 * 驾车路线规划
 */
export const drivingDirection = async (origin: string, destination: string) => {
  return fetchAPI('_direction_driving', { origin, destination });
};

/**
 * 公交路线规划
 */
export const transitDirection = async (origin: string, destination: string, city: string = '上海', cityd: string = '上海') => {
  return fetchAPI('_direction_transit_integrated', { origin, destination, city, cityd });
};

/**
 * 步行路线规划
 */
export const walkingDirection = async (origin: string, destination: string) => {
  return fetchAPI('_direction_walking', { origin, destination });
};

/**
 * 距离测量
 */
export const calculateDistance = async (origins: string, destination: string, type: string = '1') => {
  return fetchAPI('_distance', { origins, destination, type });
};

/**
 * 关键词搜索
 */
export const poiSearch = async (keywords: string, city?: string) => {
  const params: any = { keywords };
  if (city) params.city = city;
  
  return fetchAPI('_text_search', params);
};

/**
 * 周边搜索
 */
export const aroundSearch = async (location: string, keywords?: string, radius: string = '1000') => {
  const params: any = { location, radius };
  if (keywords) params.keywords = keywords;
  
  return fetchAPI('_around_search', params);
};

/**
 * 批量地理编码 - 一次性处理多个地址
 * 使用限流器的批量处理功能，避免并发限制错误
 */
export const batchGeocode = async (addresses: string[]) => {
  console.log(`批量地理编码处理 ${addresses.length} 个地址`);
  
  // 创建地理编码请求函数数组
  const geoFunctions = addresses.map(address => {
    return () => geocode(address);
  });
  
  // 使用限流器的批量功能处理请求
  return requestLimiter.batchSubmit('service', geoFunctions, { 
    maxConcurrent: 1,  // 一次只处理1个请求
    delay: 500        // 请求之间间隔500ms
  });
};

/**
 * 批量距离计算 - 一次性计算多个距离
 */
export const batchCalculateDistance = async (
  originPoints: string[], 
  destinationPoint: string, 
  type: string = '1'
) => {
  console.log(`批量计算 ${originPoints.length} 个距离`);
  
  // 每批处理的点数
  const batchSize = 5;
  const results = [];
  
  // 分批处理，避免单次请求参数过多
  for (let i = 0; i < originPoints.length; i += batchSize) {
    const batch = originPoints.slice(i, i + batchSize);
    const origins = batch.join('|');
    
    // 延迟处理每批请求
    if (i > 0) {
      await new Promise(resolve => setTimeout(resolve, 1000));
    }
    
    try {
      const response = await calculateDistance(origins, destinationPoint, type);
      results.push(...(response as any).results);
    } catch (error) {
      console.error(`批量距离计算失败 (批次 ${i / batchSize + 1}):`, error);
      
      // 如果失败，改为逐个处理这批点
      for (const origin of batch) {
        try {
          await new Promise(resolve => setTimeout(resolve, 500));
          const response = await calculateDistance(origin, destinationPoint, type);
          results.push(...(response as any).results);
        } catch (innerError) {
          console.error(`单点距离计算失败:`, innerError);
          // 添加一个失败标记
          results.push({ 
            origin_id: origin,
            error: true,
            distance: null,
            duration: null
          });
        }
      }
    }
  }
  
  return { status: '1', info: 'OK', results };
};